package com.atguigu.spzx.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.atguigu.spzx.common.exception.SpzxException;
import com.atguigu.spzx.model.entity.order.OrderInfo;
import com.atguigu.spzx.model.entity.order.OrderItem;
import com.atguigu.spzx.model.entity.pay.PaymentInfo;
import com.atguigu.spzx.model.vo.common.Result;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.order.client.OrderClient;
import com.atguigu.spzx.pay.config.AlipayConfig;
import com.atguigu.spzx.pay.mapper.PaymentInfoMapper;
import com.atguigu.spzx.pay.service.PaymentInfoService;
import com.atguigu.spzx.product.client.ProductClient;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class PaymentInfoServiceImpl implements PaymentInfoService {
    @Resource
    PaymentInfoMapper paymentInfoMapper;
    @Resource
    OrderClient orderClient;
    @Resource
    ProductClient productClient;
    @Override
    public PaymentInfo findPaymentInfoByOrderNo(String orderNo) {
        return paymentInfoMapper.findPaymentInfoByOrderNo(orderNo);
    }

    @Override
    public void save(PaymentInfo paymentInfo) {
        paymentInfoMapper.save(paymentInfo);
    }

    @Override
    public void update(PaymentInfo paymentInfo) {
        paymentInfoMapper.update(paymentInfo);
    }

    @Override
    public String notifyUrl(Map<String, String> params) {
        try {
            //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            //商户订单号： 支付宝支付下单时 传给支付宝的   可以查询到用户支付的是哪个订单
            String out_trade_no = params.get("out_trade_no");
            //支付宝交易号
            String trade_no = params.get("trade_no");
            //交易状态
            String trade_status = params.get("trade_status");
            //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            //计算得出通知验证结果
            //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
            boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY,
                    AlipayConfig.CHARSET, "RSA2");

            //1、验证签名成功：支付宝回传的支付参数正确，没有被篡改
            if (verify_result) {//验证成功
                //需要保证幂等性 + 从本地交易日志表获取订单编号对应的支付金额进行比较
                //根据订单编号查询交易日志
                PaymentInfo paymentInfo = paymentInfoMapper.findPaymentInfoByOrderNo(out_trade_no);
                if(paymentInfo==null ){
                    //查询不到订单的交易日志 非法请求
                    System.out.println("非法请求，交易日志不存在");
                    return "fail";
                }
                //请在这里加上商户的业务逻辑程序代码
                //2、订单的状态是否正确 + 验证用户支付的订单金额是否和订单应支付金额一致
                if (!"TRADE_SUCCESS".equals(trade_status)) {
                    //5、更新交易成功的日志
                    paymentInfo.setCallbackTime(new Date());
                    //将支付宝回调的所有参数都设置
                    paymentInfo.setCallbackContent(JSON.toJSONString(params));
                    paymentInfo.setOutTradeNo(trade_no);
                    paymentInfo.setPaymentStatus(-1);
                    update(paymentInfo);
                    return "fail";
                }
                if(!paymentInfo.getAmount().equals(new BigDecimal(params.get("buyer_pay_amount")))){
                    return "fail";
                }

                Integer paymentStatus = paymentInfo.getPaymentStatus();
                if( paymentStatus!=0){//保证幂等性
                    //状态为1 代表上一次回调被处理时 交易成功
                    return paymentStatus==1?"success":"fail";
                }

                //3、更新订单的状态
                // orderItem的库存和销量：product
                orderClient.updateOrderPayStatus(out_trade_no);
                //4、更新库存、销量
                productClient.updateSkuSalesAndStockByOrderNo(out_trade_no);
                //5、更新交易成功的日志
                paymentInfo.setCallbackTime(new Date());
                //将支付宝回调的所有参数都设置
                paymentInfo.setCallbackContent(JSON.toJSONString(params));
                paymentInfo.setOutTradeNo(trade_no);
                paymentInfo.setPaymentStatus(1);
                update(paymentInfo);
                return "success";

            }
        } catch (AlipayApiException e) {
            //throw new SpzxException(ResultCodeEnum.ERROR,e);
            //支付失败
            e.printStackTrace();
        }
        return "fail";
    }

    @Override
    public String returnUrl(HttpServletRequest request) {
        try {
            Map<String, String> params = new HashMap<String, String>();
            Map requestParams = request.getParameterMap();
            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                //乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            }
            //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            //计算得出通知验证结果   验证签名
            //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
            boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY,
                    AlipayConfig.CHARSET, "RSA2");

            if (verify_result) {//验证成功
                //用户支付成功：跳转到支付成功页面
                return "redirect:http://192.168.1.170/#/pages/order/order?state=0";
            } else {
                //该页面可做页面美工编辑
                //跳转到支付失败页面
                return "redirect:http://192.168.1.170";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "redirect:http://192.168.1.170";
        }
    }

    @Override
    public Result submitAlipay(Long orderNo) {

        // 商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = String.valueOf(orderNo);
        // 订单名称，必填
        //根据订单编号查询订单详情数据：
        Result<OrderInfo> result = orderClient.findOrderByOrderNo(orderNo);
        if (result.getCode() != 200) {
            throw new SpzxException(ResultCodeEnum.ERROR, null);
        }
        OrderInfo orderInfo = result.getData();
        String subject = StringUtils.join(orderInfo
                        .getOrderItemList().stream()
                        .map(OrderItem::getSkuName)
                        .collect(Collectors.toList()),
                ",");
        // 付款金额，必填
        String total_amount = orderInfo.getTotalAmount().toString();
        // 销售产品码 必填
        String product_code = "QUICK_WAP_WAY";
        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        AlipayClient client =
                new DefaultAlipayClient(AlipayConfig.URL,
                        AlipayConfig.APPID,
                        AlipayConfig.RSA_PRIVATE_KEY,
                        AlipayConfig.FORMAT,
                        AlipayConfig.CHARSET,
                        AlipayConfig.ALIPAY_PUBLIC_KEY,
                        AlipayConfig.SIGNTYPE);
        AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);//订单编号
        model.setSubject(subject);//主题
        model.setTotalAmount(total_amount);//支付金额
//        model.setBody(body);
//        model.setTimeoutExpress(timeout_express);
        model.setProductCode(product_code);//支付方式
        alipay_request.setBizModel(model);
        // 设置异步通知地址： 用户支付后 支付宝异步通知支付结果给我们项目时 我们项目接收通知的接口地址
        alipay_request.setNotifyUrl(AlipayConfig.notify_url);
        // 设置同步地址： 用户支付后 支付宝同步通知支付结果给我们时 我们的接口地址
        alipay_request.setReturnUrl(AlipayConfig.return_url);

        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单： 就是自动提交的表单字符串
            form = client.pageExecute(alipay_request).getBody();
            System.out.println("form = " + form);
            //保存交易日志：
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setUserId(orderInfo.getUserId());
            paymentInfo.setOrderNo(orderInfo.getOrderNo());
            paymentInfo.setPayType(2);
            paymentInfo.setAmount(orderInfo.getTotalAmount());
            paymentInfo.setContent(subject);
            paymentInfo.setPaymentStatus(0);
            //调用方法时尽量使用容器中装配的对象来调用 避免aop失效
            paymentInfoMapper.save(paymentInfo);
            return Result.ok().data(form);
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new SpzxException(ResultCodeEnum.ALI_PAY_ERROR, e);
        }

    }
}
